// Package repository implements database access for activity related operations.
package repository

import (
	"context"
	"database/sql"
	"time"

	"github.com/we-pay-kit/we-pay-kit/internal/db"
)

type ActivityRepository struct {
	db *db.DB
}

func NewActivityRepository(database *db.DB) *ActivityRepository {
	return &ActivityRepository{db: database}
}

func (r *ActivityRepository) Create(ctx context.Context, a *ActivityConfig) (int64, error) {
	q := `INSERT INTO activity_config(
            activity_name, activity_type, start_time, end_time,
            total_budget, single_max_amount, single_min_amount, rule_config,
            status, created_by
        ) VALUES($1,$2,$3,$4,$5,$6,$7,$8,$9,$10) RETURNING id`
	var id int64
	err := r.db.QueryRowContext(ctx, q,
		a.ActivityName, a.ActivityType, a.StartTime, a.EndTime,
		a.TotalBudget, a.SingleMaxAmount, a.SingleMinAmount, a.RuleConfig,
		a.Status, a.CreatedBy,
	).Scan(&id)
	return id, err
}

func (r *ActivityRepository) GetByID(ctx context.Context, id int64) (*ActivityConfig, error) {
	q := `SELECT id, activity_name, activity_type, start_time, end_time,
                 total_budget, single_max_amount, single_min_amount, rule_config,
                 status, created_by, created_at, updated_by, updated_at
          FROM activity_config WHERE id=$1`
	row := r.db.QueryRowContext(ctx, q, id)
	var a ActivityConfig
	var updBy sql.NullString
	if err := row.Scan(
		&a.ID, &a.ActivityName, &a.ActivityType, &a.StartTime, &a.EndTime,
		&a.TotalBudget, &a.SingleMaxAmount, &a.SingleMinAmount, &a.RuleConfig,
		&a.Status, &a.CreatedBy, &a.CreatedAt, &updBy, &a.UpdatedAt,
	); err != nil {
		return nil, err
	}
	if updBy.Valid {
		a.UpdatedBy = &updBy.String
	}
	return &a, nil
}

func (r *ActivityRepository) List(ctx context.Context, limit, offset int) ([]ActivityConfig, error) {
	if limit <= 0 {
		limit = 20
	}
	q := `SELECT id, activity_name, activity_type, start_time, end_time,
                 total_budget, single_max_amount, single_min_amount, rule_config,
                 status, created_by, created_at, updated_by, updated_at
          FROM activity_config ORDER BY id DESC LIMIT $1 OFFSET $2`
	rows, err := r.db.QueryContext(ctx, q, limit, offset)
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	res := make([]ActivityConfig, 0, limit)
	for rows.Next() {
		var a ActivityConfig
		var updBy sql.NullString
		if err := rows.Scan(
			&a.ID, &a.ActivityName, &a.ActivityType, &a.StartTime, &a.EndTime,
			&a.TotalBudget, &a.SingleMaxAmount, &a.SingleMinAmount, &a.RuleConfig,
			&a.Status, &a.CreatedBy, &a.CreatedAt, &updBy, &a.UpdatedAt,
		); err != nil {
			return nil, err
		}
		if updBy.Valid {
			a.UpdatedBy = &updBy.String
		}
		res = append(res, a)
	}
	return res, rows.Err()
}

func (r *ActivityRepository) UpdateStatus(ctx context.Context, id int64, status, updatedBy string) error {
	q := `UPDATE activity_config SET status=$1, updated_by=$2, updated_at=$3 WHERE id=$4`
	_, err := r.db.ExecContext(ctx, q, status, updatedBy, time.Now(), id)
	return err
}

func (r *ActivityRepository) Delete(ctx context.Context, id int64) error {
	q := `DELETE FROM activity_config WHERE id=$1`
	_, err := r.db.ExecContext(ctx, q, id)
	return err
}
